import {
    Box,
    Checkbox,
    CircularProgress,
    DialogContent,
    DialogTitle,
    FormControlLabel,
    Typography
} from '@mui/material';
import debounce from 'lodash-es/debounce';
import { useRouter } from 'next/router';
import React, { useCallback, useEffect, useState } from 'react';
import create from 'zustand';

import Member from '../../api/member/member';
import MemberManager from '../../api/member/member-manager';
import PayrollGroupMember from '../../api/payroll-group-member/payroll-group-member';
import PayrollGroupMemberManager from '../../api/payroll-group-member/payroll-group-member-manager';
import { GFSLoadingButton } from '../shared/button/gfs-button';
import GFSDialog from '../shared/dialogs/gfs-dialog';
import { useStyles } from '../shared/dialogs/UIs/styled-mui-dialog';
import { GfsInputBase } from '../shared/forms';

interface AddScholarStore {
    open: boolean;
    close?: () => void;
    data?: AddScholarData;
    onSubmit?: (boolean) => void;
}

export interface AddScholarData {
    payrollGroupMembers: PayrollGroupMember[];
}

const useAddScholarStore = create<AddScholarStore>((set) => ({
    open: false,
    close: () => set({ open: false }),
    data: {} as AddScholarData,
    onSubmit: undefined
}));

export const addScholarDialog = ({ onSubmit, data }: AddScholarStore) => {
    useAddScholarStore.setState({
        open: true,
        onSubmit,
        data
    });
};

export const AddMemberPopup = () => {
    const style = useStyles();
    const router = useRouter();
    const { open, close, data, onSubmit } = useAddScholarStore();
    const { payrollGroupMembers } = data;
    const [status, setStatus] = useState<{ submit: boolean; getList: boolean }>({
        submit: false,
        getList: false
    });
    const [selected, setSelected] = useState<any[]>([]);
    const [items, setItems] = useState<Member[]>([]);
    const [searchText, setSearchText] = useState<string>('');

    useEffect(() => {
        if (data.payrollGroupMembers && open) {
            getMembersDebounce(searchText);
        }
    }, [data.payrollGroupMembers, open, searchText]);

    const getMembers = (searchText = '') => {
        setStatus((status) => ({ ...status, getList: true }));
        MemberManager.search(searchText)
            .then((res) => {
                const filtered = res.filter(
                    (item) => !payrollGroupMembers.find((it) => it.member.id === item.id)
                );
                setItems(filtered);
            })
            .finally(() => setStatus((status) => ({ ...status, getList: false })));
    };

    const getMembersDebounce = useCallback(
        debounce((searchText) => getMembers(searchText), 200),
        [payrollGroupMembers]
    );

    const onChange = (checked, member_id) => {
        let temp = [...selected];
        if (checked) {
            temp.push(member_id);
        } else {
            temp = selected.filter((it) => it !== member_id);
        }
        setSelected(temp);
    };

    const onAddScholar = () => {
        const apiCalls = [];
        const id = parseInt(router.query['id'].toString());
        setStatus((status) => ({ ...status, submit: true }));
        for (const member_id of selected) {
            const call = PayrollGroupMemberManager.create(id, member_id);
            apiCalls.push(call);
        }
        Promise.allSettled(apiCalls)
            .then((res) => {
                const successMembers = res
                    .filter((item) => item.status === 'fulfilled')
                    .map((it: any) => it.value)
                    .filter((member) => !member.error);
                const newMembers = successMembers.map(({ group_member }) => {
                    const newMember = new PayrollGroupMember();
                    newMember.id = group_member.id;
                    newMember.member = items.find((item) => item.id === group_member.member_id);
                    return newMember;
                });
                onClose();
                onSubmit(newMembers);
            })
            .finally(() => setStatus((status) => ({ ...status, submit: false })));
    };

    const onClose = () => {
        close();
        setSearchText('');
        setSelected([]);
        setItems([]);
    };

    return (
        <GFSDialog open={open}>
            <DialogTitle>
                Add member(s)
                <Box
                    component="img"
                    alt="Icon"
                    src={'/close.svg'}
                    sx={{ cursor: 'pointer' }}
                    onClick={onClose}
                />
            </DialogTitle>
            <DialogContent className={`${style.center}`}>
                <Box sx={{ p: 4, pt: 2, width: '100%', maxHeight: 600 }}>
                    <Box mb={4} position="relative">
                        <GfsInputBase
                            id="search"
                            sx={{ width: '100%' }}
                            placeholder="Search"
                            value={searchText}
                            onChange={(e) => setSearchText(e.target.value)}
                        />
                    </Box>

                    {status.getList ? (
                        <Box
                            display="flex"
                            justifyContent="center"
                            alignItems="center"
                            sx={{ pt: 4 }}
                        >
                            <CircularProgress sx={{ color: '#ffffff' }} />
                        </Box>
                    ) : (
                        <>
                            {!items.length && (
                                <Typography variant="h4" color="white" mb={4}>
                                    No available member
                                </Typography>
                            )}
                            {items.map((item) => (
                                <Box mb={4} position="relative" key={item.id}>
                                    <FormControlLabel
                                        control={
                                            <Checkbox
                                                onChange={(e) =>
                                                    onChange(e.target.checked, item.id)
                                                }
                                            />
                                        }
                                        label={
                                            <Typography variant="h6" color="white">
                                                {item.name}
                                            </Typography>
                                        }
                                        sx={{ width: '100%' }}
                                    />
                                </Box>
                            ))}

                            <GFSLoadingButton
                                onClick={onAddScholar}
                                fullWidth
                                disabled={!items.length || !selected.length}
                                loading={status.submit}
                            >
                                Add
                            </GFSLoadingButton>
                        </>
                    )}
                </Box>
            </DialogContent>
        </GFSDialog>
    );
};
